package com.imooc.miaosha.controller;

import com.imooc.miaosha.access.AccessLimit;
import com.imooc.miaosha.domain.Goods;
import com.imooc.miaosha.domain.MiaoShaUser;
import com.imooc.miaosha.domain.MiaoshaOrder;
import com.imooc.miaosha.domain.OrderInfo;
import com.imooc.miaosha.rabbitmq.MQSender;
import com.imooc.miaosha.rabbitmq.MiaoshaMessage;
import com.imooc.miaosha.redis.GoodsKey;
import com.imooc.miaosha.redis.RedisService;
import com.imooc.miaosha.result.CodeMsg;
import com.imooc.miaosha.result.Result;
import com.imooc.miaosha.service.GoodsService;
import com.imooc.miaosha.service.MiaoshaService;
import com.imooc.miaosha.service.OrderService;
import com.imooc.miaosha.vo.GoodsVo;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;

@Controller
@RequestMapping("/miaosha")
public class MiaoshaController implements InitializingBean {
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private MiaoshaService miaoshaService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private MQSender mqSender;

    //这个HashMap用来当Redis缓存中的数量秒杀完了，防止再次访问
    private HashMap<Long,Boolean> map = new HashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        //系统启动的时候，就将数据存入Redis

        //加载所有秒杀商品
        List<GoodsVo> goodsVos = goodsService.listGoodsVo();
        if(goodsVos == null)
            return;
        //存入Redis中，各秒杀商品的数量
        for (GoodsVo good : goodsVos){
            redisService.set(GoodsKey.miaoshaGoodsStockPrefix,""+good.getId(),good.getStockCount());
            map.put(good.getId(),false);
        }

    }

    /**
     * QPS 110
     * 1000 * 10
     * @param model
     * @param user
     * @param goodsId
     * @return
     */
    @RequestMapping(value = "/{path}/do_miaosha",method = RequestMethod.POST)
    @ResponseBody
    public Result<Integer> doMiaosha(Model model, MiaoShaUser user,
                                     @RequestParam("goodsId")long goodsId, @PathVariable(value = "path")String path){
        //user不能为空，空了去登陆
        if(user == null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }

        boolean check = miaoshaService.checkPath(user.getId(),goodsId,path);
        if(! check){
            return Result.error(CodeMsg.REQUEST_ILLEGAL);
        }

        //HashMap内存标记，减少Redis访问时间
        boolean over = map.get(goodsId);
        if(over){
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }

        //收到请求，预减库存
        Long count = redisService.decr(GoodsKey.miaoshaGoodsStockPrefix, "" + goodsId);
        if(count <= 0){
            map.put(goodsId,true);
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }

        //判断是否已经秒杀过了
        MiaoshaOrder miaoshaOrder = orderService.selectMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
        if(miaoshaOrder != null)
            return Result.error(CodeMsg.REPEATE_MIAOSHA);

        //加入消息队列
        MiaoshaMessage miaoshaMessage = new MiaoshaMessage();
        miaoshaMessage.setGoodsId(goodsId);
        miaoshaMessage.setMiaoShaUser(user);
        mqSender.sendMiaoshaMessage(miaoshaMessage);

        return Result.success(0);
    }

    @RequestMapping(value = "/verifyCode",method = RequestMethod.GET)
    @ResponseBody
    public Result<String> getMiaoshaVerifyCode(HttpServletResponse response,MiaoShaUser user,
                                               @RequestParam("goodsId")long goodsId){
        if(user == null)
            return Result.error(CodeMsg.SESSION_ERROR);

        try {
            BufferedImage image  = miaoshaService.createVerifyCode(user, goodsId);
            OutputStream out = response.getOutputStream();
            ImageIO.write(image, "JPEG", out);
            out.flush();
            out.close();
            return null;
        }catch(Exception e) {
            e.printStackTrace();
            return Result.error(CodeMsg.MIAOSHA_FAIL);
        }

    }

    /**
     * orderId 成功
     * -1 秒杀失败
     * 0 继续轮询
     * @param miaoShaUser
     * @param goodsId
     * @return
     */
    @RequestMapping(value = "/result",method = RequestMethod.GET)
    @ResponseBody
    public Result<Long> miaoshaResult(MiaoShaUser miaoShaUser,
                                      @RequestParam("goodsId")long goodsId){
        if(miaoShaUser == null)
            return Result.error(CodeMsg.SESSION_ERROR);

        long result = miaoshaService.getMiaoshaResult(miaoShaUser.getId(),goodsId);
        return Result.success(result);
    }

    @AccessLimit(seconds = 5,maxCount = 5,needLogin = true)
    @ResponseBody
    @RequestMapping(value = "/path",method = RequestMethod.GET)
    public Result<String> getMiaoshaPath(MiaoShaUser user,@RequestParam("goodsId")long goodsId,
                                         @RequestParam(value = "verifyCode",defaultValue = "0")int verifyCode){
        if(user == null)
            return Result.error(CodeMsg.SESSION_ERROR);

        boolean check = miaoshaService.checkVerifyCode(user,goodsId,verifyCode);
        if(! check)
            return Result.error(CodeMsg.YAN_ZHENG_MA_CUO_WU);

        String path = miaoshaService.createMiaoshaPath(user,goodsId);

        return Result.success(path);
    }




    //下面的是做接口优化集成rabbitMQ注掉的
/*    @RequestMapping(value = "/do_miaosha",method = RequestMethod.POST)
    @ResponseBody
    public Result<OrderInfo> doMiaosha(Model model, MiaoShaUser user, @RequestParam("goodsId")long goodsId){
        //user不能为空，空了去登陆
        if(user == null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }

        //判断库存，没有库存返回错误页面
        GoodsVo goodsVo = goodsService.getGoodsVoByGoodsId(goodsId);
        Integer stockCount = goodsVo.getStockCount();
        if(stockCount <= 0){
            //model.addAttribute("errmsg", CodeMsg.MIAO_SHA_OVER.getMsg());
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }

        //判断是否秒杀过，只能秒杀一次
        MiaoshaOrder miaoshaOrder = orderService.selectMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
        if(miaoshaOrder != null){
            //model.addAttribute("errmsg",CodeMsg.REPEATE_MIAOSHA.getMsg());
            return Result.error(CodeMsg.REPEATE_MIAOSHA);
        }

        //开始正常秒杀，存在库存且没秒杀过
        //库存减一，总库存减一，创建订单，创建秒杀订单
        OrderInfo orderInfo = miaoshaService.miaosha(user, goodsVo);

       *//* model.addAttribute("orderInfo",orderInfo);
        model.addAttribute("goods",goodsVo);*//*

        return Result.success(orderInfo);
    }*/

    //下边的这个是静态化优化时注释掉的
/*    @RequestMapping("/do_miaosha")
    public String doMiaosha(Model model, MiaoShaUser user, @RequestParam("goodsId")long goodsId){
        //user不能为空，空了去登陆
        if(user == null){
            return "login";
        }

        //判断库存，没有库存返回错误页面
        GoodsVo goodsVo = goodsService.getGoodsVoByGoodsId(goodsId);
        Integer stockCount = goodsVo.getStockCount();
        if(stockCount <= 0){
            model.addAttribute("errmsg", CodeMsg.MIAO_SHA_OVER.getMsg());
            return "miaosha_fail";
        }

        //判断是否秒杀过，只能秒杀一次
        MiaoshaOrder miaoshaOrder = orderService.selectMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
        if(miaoshaOrder != null){
            model.addAttribute("errmsg",CodeMsg.REPEATE_MIAOSHA.getMsg());
            return "miaosha_fail";
        }

        //开始正常秒杀，存在库存且没秒杀过
        //库存减一，总库存减一，创建订单，创建秒杀订单
        OrderInfo orderInfo = miaoshaService.miaosha(user, goodsVo);

        model.addAttribute("orderInfo",orderInfo);
        model.addAttribute("goods",goodsVo);

        return "order_detail";
    }*/
}
